#ifndef MESH_H
#define MESH_H

#include "Vertex.h"

class Mesh
{
public:
    enum Type : uint8_t
    {
        texture = 0,
        color = 1
    };
private:
    Vertex** vPtr = nullptr;
    size_t* elementPtr = nullptr;
    size_t triangleTotal = 0;
    size_t vertexTotal = 0;
    Type type = texture;
public:
    ~Mesh()
    {
        for (int i = 0; i < vertexTotal; ++i)
            delete vPtr[i];
        delete vPtr;
        delete elementPtr;
    }
    [[nodiscard]] inline size_t GetTriangleTotal() const
    {
        return triangleTotal;
    }
    [[nodiscard]] inline const Vertex& GetTriangleVertex(size_t triangleIndex, size_t VertexIndex) const
    {
        if (vPtr == nullptr)
            throw std::bad_exception();
        if (elementPtr == nullptr)
            throw std::bad_exception();
        if (VertexIndex > 2)
            throw std::bad_exception();
        return *vPtr[elementPtr[triangleIndex * 3 + VertexIndex]];
    }
    [[nodiscard]] inline Type GetType() const
    {
        return type;
    }

private:
    Mesh() = default;
public:
    static Mesh CreateCubeTexture(float size)
    {
        float half = size / 2;
        Mesh mesh = Mesh();
        mesh.type = texture;
        mesh.triangleTotal = 12;
        mesh.vPtr = new Vertex*[24]
        {
            // 第一面
            new Vertex(-half, -half, -half, 0, 0),
            new Vertex(half, -half, -half, 1, 0),
            new Vertex(half, half, -half, 1, 1),
            new Vertex(-half, half, -half, 0, 1),

            // 第二面
            new Vertex(half, -half, -half, 0, 0),
            new Vertex(half, -half, half, 1, 0),
            new Vertex(half, half, half, 1, 1),
            new Vertex(half, half, -half, 0, 1),

            // 第三面
            new Vertex(half, -half, half, 0, 0),
            new Vertex(-half, -half, half, 1, 0),
            new Vertex(-half, half, half, 1, 1),
            new Vertex(half, half, half, 0, 1),

            // 第四面
            new Vertex(-half, -half, half, 0, 0),
            new Vertex(-half, -half, -half, 1, 0),
            new Vertex(-half, half, -half, 1, 1),
            new Vertex(-half, half, half, 0, 1),

            // 第五面
            new Vertex(-half, -half, half, 0, 0),
            new Vertex(half, -half, half, 1, 0),
            new Vertex(half, -half, -half, 1, 1),
            new Vertex(-half, -half, -half, 0, 1),

            // 第六面
            new Vertex(half, half, half, 0, 0),
            new Vertex(-half, half, half, 1, 0),
            new Vertex(-half, half, -half, 1, 1),
            new Vertex(half, half, -half, 0, 1),
        };
        mesh.elementPtr = new size_t[12 * 3];
        for (size_t i = 0; i < 6; ++i)
        {
            size_t ftp = (i * 2 + 0) * 3;
            size_t stp = (i * 2 + 1) * 3;
            size_t vo = i * 4;

            // 第一个三角形
            mesh.elementPtr[ftp + 0] = 0 + vo;
            mesh.elementPtr[ftp + 1] = 1 + vo;
            mesh.elementPtr[ftp + 2] = 3 + vo;

            // 第二个三角形
            mesh.elementPtr[stp + 0] = 1 + vo;
            mesh.elementPtr[stp + 1] = 2 + vo;
            mesh.elementPtr[stp + 2] = 3 + vo;
        }

        return mesh;
    }
    static Mesh CreateJioJioTexture(float size)
    {
        Mesh mesh = Mesh();
        mesh.type = texture;
        mesh.triangleTotal = 3;
        mesh.vPtr = new Vertex*[4]
                {
                        new Vertex(0, 0, 0, 0, 0),
                        new Vertex(1, 0, 0, 0, 0),
                        new Vertex(0, 1, 0, 0, 0),
                        new Vertex(0, 0, 1, 0, 0),
                };
        mesh.elementPtr = new size_t[3 * 3]
                {
                        0, 1, 2,
                        0, 2, 3,
                        0, 3, 1
                };

        return mesh;
    }
    static Mesh CreateSingleTriangleTexture(float size)
    {
        Mesh mesh = Mesh();
        mesh.type = texture;
        mesh.triangleTotal = 1;
        mesh.vPtr = new Vertex*[3]
                {
                        new Vertex(0, 0, 1, 0, 0),
                        new Vertex(1, 0, 0, 0, 0),
                        new Vertex(0, 1, 0, 0, 0),
                };
        mesh.elementPtr = new size_t[1 * 3]
                {
                        0, 1, 2,
                };

        return mesh;
    }
    static Mesh CreateSinglePlantTexture(float size)
    {
        Mesh mesh = Mesh();
        mesh.type = texture;
        mesh.triangleTotal = 2;
        mesh.vPtr = new Vertex*[4]
                {
                        new Vertex(0, 0, 1, 0, 0),
                        new Vertex(1, 0, 1, 0, 0),
                        new Vertex(1, 0, 0, 0, 0),
                        new Vertex(0, 0, 0, 0, 0)
                };
        mesh.elementPtr = new size_t[2 * 3]
                {
                        0, 1, 3,
                        1, 2, 3
                };

        return mesh;
    }
};

#endif //MESH_H


